package com.drg.center.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.drg.center.dao.SysDictItemDAO;
import com.drg.center.entity.param.SysDictItemAddDTO;
import com.drg.center.entity.param.SysDictItemEditDTO;
import com.drg.center.entity.param.SysDictItemListDTO;
import com.drg.center.entity.result.SysDictItemVO;
import com.google.common.collect.Maps;
import com.guaike.core.entity.context.ContextHolder;
import com.guaike.core.entity.enums.EnableStatusEnum;
import com.guaike.core.entity.result.ItemVO;
import com.guaike.core.entity.result.Result;
import com.guaike.core.redis.constant.CacheKeyConstant;
import com.guaike.core.redis.helper.DictCacheHelper;
import com.guaike.core.utils.ListUtil;
import com.drg.center.dao.SysDictDAO;
import com.drg.center.entity.SysDictItemPO;
import com.drg.center.entity.SysDictPO;
import com.drg.center.service.DictItemService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: zhangxilin
 * @Date: 2023/10/26
 */
@Slf4j
@Service
public class DictItemServiceImpl implements DictItemService {

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private DictCacheHelper dictCacheHelper;

    @Autowired
    private SysDictItemDAO sysDictItemDAO;
    @Autowired
    private SysDictDAO sysDictDAO;

    @Override
    public Result<List<SysDictItemVO>> list(SysDictItemListDTO param) {
        List<SysDictItemVO> list = Lists.newArrayList();
        List<SysDictItemPO> poList = sysDictItemDAO.list(param);
        if(CollectionUtils.isEmpty(poList)){
            return Result.success().data(list).build();
        }
        for(SysDictItemPO po: poList){
            SysDictItemVO itemVO = new SysDictItemVO();
            itemVO.setId(po.getId());
            itemVO.setDictCode(po.getDictCode());
            itemVO.setItemCode(po.getItemCode());
            itemVO.setItemName(po.getItemName());
            itemVO.setStatus(po.getStatus());
            itemVO.setSortIndex(po.getSortIndex());
            itemVO.setRemark(po.getRemark());
            list.add(itemVO);
        }
        return Result.success().data(list).build();
    }

    @Override
    public Map<String, List<SysDictItemVO>> findMap(List<String> dictCodeList) {
        if(CollectionUtils.isEmpty(dictCodeList)){
            return Maps.newHashMap();
        }
        List<SysDictItemPO> poList = sysDictItemDAO.findIn(SysDictItemPO::getDictCode, dictCodeList, SysDictItemPO::getSortIndex, true);
        if(CollectionUtils.isEmpty(poList)){
            return Maps.newHashMap();
        }
        Map<String, List<SysDictItemVO>> map = Maps.newHashMap();

        for(SysDictItemPO po: poList){
            List<SysDictItemVO> itemList = map.get(po.getDictCode());
            if(CollectionUtils.isEmpty(itemList)){
                itemList = Lists.newArrayList();
            }
            SysDictItemVO itemVO = new SysDictItemVO();
            itemVO.setId(po.getId());
            itemVO.setDictCode(po.getDictCode());
            itemVO.setItemCode(po.getItemCode());
            itemVO.setItemName(po.getItemName());
            itemVO.setStatus(po.getStatus());
            itemVO.setSortIndex(po.getSortIndex());
            itemVO.setRemark(po.getRemark());
            itemList.add(itemVO);
            map.put(po.getDictCode(), itemList);
        }
        return map;
    }

    @Override
    public Result<Boolean> add(SysDictItemAddDTO param) {
        EnableStatusEnum statusEnum = EnableStatusEnum.getByCode(param.getStatus());
        if(statusEnum == null){
            return Result.failure().message("状态编码传参不合法").build();
        }
        SysDictPO dictPO = sysDictDAO.findOne(SysDictPO::getDictCode,param.getDictCode());
        if(dictPO==null){
            return Result.failure().message("字典类型不存在").build();
        }

        List<SysDictItemPO> itemPOList = sysDictItemDAO.findList(param.getDictCode());
        Integer sortIndex = 0;
        if(!CollectionUtils.isEmpty(itemPOList)){
            Set<String> itemCodeSet = itemPOList.stream().map(SysDictItemPO::getItemCode).collect(Collectors.toSet());
            if(itemCodeSet.contains(param.getItemCode())){
                return Result.failure().message("字典项编号已存在").build();
            }
            SysDictItemPO lastOnePO = itemPOList.get(itemPOList.size()-1);

            sortIndex =  lastOnePO.getSortIndex() == null? 0: lastOnePO.getSortIndex()+1;
        }

        SysDictItemPO record = new SysDictItemPO();
        record.setDictCode(param.getDictCode());
        record.setItemCode(param.getItemCode());
        record.setItemName(param.getItemName());
        record.setStatus(param.getStatus());
        record.setRemark(param.getRemark());
        record.setSortIndex(sortIndex);
        sysDictItemDAO.save(record);
        this.syncCache(param.getDictCode());
        return Result.success().data(Boolean.TRUE).build();
    }

    @Override
    public Result<Boolean> edit(SysDictItemEditDTO param) {
        EnableStatusEnum statusEnum = EnableStatusEnum.getByCode(param.getStatus());
        if(statusEnum == null){
            return Result.failure().message("状态编码传参不合法").build();
        }
        SysDictItemPO record = sysDictItemDAO.findById(param.getId());
        if(record == null){
            return Result.failure().message("记录不存在").build();
        }
        if(sysDictItemDAO.isExist(record.getDictCode(),param.getItemCode(),param.getId())){
            return Result.failure().message("字典项编号已存在").build();
        }
        record.setItemCode(param.getItemCode());
        record.setItemName(param.getItemName());
        record.setRemark(param.getRemark());
        record.setSortIndex(param.getSortIndex());
        record.setStatus(param.getStatus());
        record.setUpdateUser(ContextHolder.getUserId());
        sysDictItemDAO.updateWithNull(record);
        this.syncCache(record.getDictCode());
        return Result.success().data(Boolean.TRUE).build();
    }

    @Override
    public Result<Boolean> delete(Long id) {
        SysDictItemPO record = sysDictItemDAO.findById(id);
        if(record == null){
            return Result.failure().message("记录不存在").build();
        }
        sysDictItemDAO.del(id);
        this.syncCache(record.getDictCode());
        return Result.success().data(Boolean.TRUE).build();
    }

    @Override
    public void syncCache(String dictCode) {
        List<SysDictItemPO> itemPOList = sysDictItemDAO.findList(dictCode);

        List<ItemVO> list = Lists.newArrayList();
        if(!CollectionUtils.isEmpty(itemPOList)){
            list = ListUtil.copyList(itemPOList,ItemVO.class);
        }

        String key = getDictKeyInCache(dictCode);
        addToCache(key,list);

    }

    @Override
    public void syncCache() {
        List<SysDictItemPO> itemPOList = sysDictItemDAO.findList();
        if(CollectionUtils.isEmpty(itemPOList)){
            log.info("sync data is null");
            return;
        }
        Map<String,List<SysDictItemPO>> dictMap = itemPOList.stream().collect(Collectors.groupingBy(SysDictItemPO::getDictCode));
        for (Map.Entry<String, List<SysDictItemPO>> entry: dictMap.entrySet()){
            List<SysDictItemPO> sysDictItemPOList = entry.getValue();
            if(!CollectionUtils.isEmpty(sysDictItemPOList)){
                List<ItemVO> list = Lists.newArrayList();
                List<SysDictItemPO> items = sysDictItemPOList.stream().sorted(Comparator.comparing(SysDictItemPO::getSortIndex, Comparator.nullsLast(Comparator.naturalOrder()))
                        // 当sortIndex相同时，再比较anotherField字段
                        .thenComparing(SysDictItemPO::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder()))
                        // 最终结果是先按sortIndex升序，sortIndex相同或为空时按anotherField排序
                        ).collect(Collectors.toList());
                items.stream().forEach(item ->{
                    ItemVO itemVO = new ItemVO();
                    itemVO.setItemName(item.getItemName());
                    itemVO.setRemark(item.getRemark());
                    itemVO.setItemCode(StringUtils.isNotBlank(item.getItemCode())?item.getItemCode():item.getId()+"");
                    list.add(itemVO);
                });
                String key = this.getDictKeyInCache(entry.getKey());
                addToCache(key,list);
            }
        }
    }

    @Override
    public Result<Map<String, List<ItemVO>>> findDict(List<String> dictCodeList) {
        if(CollectionUtils.isEmpty(dictCodeList)){
            return Result.failure().message("请传入字典码").build();
        }
        if(dictCodeList.size()>20){
            return Result.failure().message("单次查询字典类型数量不得超过20个").build();
        }
        Map<String, List<ItemVO>> map = new HashMap<>();
        for(String dictCode: dictCodeList){
            map.put(dictCode,dictCacheHelper.getItemFromCache(dictCode));
        }
        log.info("findDict>>>>>>>:{}", JSONObject.toJSONString(map));
        return Result.success().data(map).build();
    }

    /**
     * 平台级字典KEY
     * @param dictCode
     * @return
     */
    private String getDictKeyInCache(String dictCode){
        return CacheKeyConstant.SYS_DICT_PREFIX_KEY+dictCode;
    }

    private void addToCache(String key, List<ItemVO> list){
        RList<ItemVO> rlist= redissonClient.getList(key);
        if(!CollectionUtils.isEmpty(rlist)){
            rlist.delete();
        }
        if(!CollectionUtils.isEmpty(list)){
            redissonClient.getList(key).addAll(list);
        }
    }

}
